#include "Application.h"
#include "usage.h"

Application::Application()
{
    m_ExitCode = NULL;
    m_debugger_path = NULL;
}

Application::~Application()
{
    if(m_debugger_path != NULL)
        free(m_debugger_path);
    if(m_tgdb.IsInitiolized())
        m_tgdb.Shutdown();
}

int Application::GetExitCode()
{
    return m_ExitCode;
}

/* ------------------------ */
/* Initialization functions */
/* ------------------------ */

/* Version_info: Returns version information about cgdb.
 * ------------- 
 *
 * Return:  A pointer to a static buffer, containing version info.
 */
char * Application::Version_info(void)
{
    static char buf[MAXLINE];
    sprintf (buf, "%s %s\r\n%s", "CGDB", VERSION,
            "Copyright 2002-2013 Bob Rossi, Mike Mueller and Kovalev Sergey.\n"
            "CGDB is free software, covered by the GNU General Public License, and you are\n"
            "welcome to change it and/or distribute copies of it under certain conditions.\n"
            "There is absolutely no warranty for CGDB.\n");
    return buf;
}

bool Application::Parse_long_options(int *argc, char ***argv)
{
    int c, option_index = 0, n = 1;
    const char *args = "d:hv";

#ifdef HAVE_GETOPT_H
    static struct option long_options[] = {
        {"version", 0, 0, 0},
        {"help", 0, 0, 0},
        {0, 0, 0, 0}
    };
#endif

    while (1)
    {
        opterr = 0;
#ifdef HAVE_GETOPT_H
        c = getopt_long (*argc, *argv, args, long_options, &option_index);
#else
        c = getopt (*argc, *argv, args);
#endif
        if (c == -1)
            break;

        if (((char) c) == '?')
            break;

        switch (c)
        {
            case 0:
                switch (option_index)
                {
                    case 0:
                        printf ("%s", Version_info ());
                        return false;
                    case 1:
                        usage ();
                        return false;
                    default:
                        break;
                }
                break;
            case 'v':
                printf ("%s", Version_info ());
                return false;
            case 'd':
                m_debugger_path = strdup (optarg);
                if (optarg == (*argv)[n + 1]) {
                    /* optarg is in next argv (-d foo) */
                    n += 2;
                } else {
                    /* optarg is in this argv (-dfoo) */
                    n++;
                }
                break;
            case 'h':
                usage ();
                return false;
            default:
                break;
        }
    }

    *argc -= n;
    *argv += n;

    if (**argv && strcmp(**argv, "--") == 0) {
        (*argc)--;
        (*argv)++;
    }
    return true;
}

void Application::Initialize(int argc, char** argv)
{
    if(!Parse_long_options (&argc, &argv))
        return;
    m_screen = Screen::GetInstance(); 
    if(m_ExitCode = m_screen->Initialize(&m_tgdb, m_debugger_path, argc, argv))
    {
        fprintf (stderr, "%s:%d Unable to initialize Screen", __FILE__, __LINE__);
        return;
    }
}

void Application::Run()
{
    if(GetExitCode())
        return;
    
    m_ExitCode = m_screen->MainLoop();
}

int main(int argc, char** argv)
{
    /* Uncomment to debug and attach */
#if 1 
    int c;
    read (0, &c, 1);
#endif

    Application app;
    app.Initialize(argc, argv);
    app.Run();
    return app.GetExitCode();
}






#include "def.h"
#include "Window.h"
#include "Layout.h"
#include "Sources.h"

enum WINS_{
    _FILES,
    _SRC,
    _DBG,
    _THREADS,
    _CALL_STACK,
    _MEM,
    _STACK,
    _TTY,
    _GDB,
    _ALL_TYPE
};

int main_3(int c, char** args)
{
    /* Uncomment to debug and attach */
#if 1
        int t;
            read (0, &t, 1);
#endif

    int ch;

    initscr();
    cbreak();
    noecho();
    keypad(stdscr, TRUE);
    start_color();
    use_default_colors (); 
    hl_groups_instance = hl_groups_initialize ();
    if (!hl_groups_instance)
        return 3;

    if (hl_groups_setup (hl_groups_instance) == -1)
        return 3;
    
    mvprintw(0, 0, "q - For exit");
    {    
        Sources win[_ALL_TYPE];
        HLayout layout;
        HLayout h_code_layout;
        HLayout h_thr_call_layout;
        HLayout h_mem_layout;

        VLayout v_code_layout;
        VLayout v_thr_call_layout;
        VLayout v_mem_layout;
        VLayout v_tty_layout;
        VLayout v_gdb_layout;

        layout.Locate(0,0, LINES, COLS);
        layout.Enable();
        h_code_layout.Enable();
        h_thr_call_layout.Enable();
        h_mem_layout.Enable();
        v_code_layout.Enable();
        v_thr_call_layout.Enable();
        v_mem_layout.Enable();
        v_tty_layout.Enable();
        v_gdb_layout.Enable();

        layout.AddWindow(&win[_FILES]);

        h_code_layout.AddWindow(&win[_SRC]);
        h_code_layout.AddWindow(&win[_DBG]);
        v_code_layout.AddWindow(&h_code_layout);
        
        h_thr_call_layout.AddWindow(&win[_THREADS]);
        h_thr_call_layout.AddWindow(&win[_CALL_STACK]);
        v_thr_call_layout.AddWindow(&h_thr_call_layout);


        h_mem_layout.AddWindow(&win[_MEM]);
        h_mem_layout.AddWindow(&win[_STACK]);
        v_mem_layout.AddWindow(&h_mem_layout);

        v_tty_layout.AddWindow(&win[_TTY]);

        v_gdb_layout.AddWindow(&win[_GDB]);

        v_tty_layout.AddWindow(&v_gdb_layout);
        v_mem_layout.AddWindow(&v_tty_layout);
        v_thr_call_layout.AddWindow(&v_mem_layout);
        v_code_layout.AddWindow(&v_thr_call_layout);
        layout.AddWindow(&v_code_layout);


        int curr_win = 0;
        for (int i = 0; i < _ALL_TYPE; i++) {
            win[i].Enable();
            win[i].Paint();
        }

        while((ch = getch()) != 'q')
        {   
            switch(ch)
            {
                case KEY_DOWN:
                    layout.Move(0, 1);
                    break;
                case KEY_UP:
                    layout.Move(0, -1);
                    break;
                case KEY_LEFT:
                    layout.Move(-1, 0);
                    break;
                case KEY_RIGHT:
                    layout.Move(1, 0);
                    break;
                case 's':
                    layout.Resize_RB(0, 1);
                    break;
                case 'w':
                    layout.Resize_RB(0, -1);
                    break;
                case 'a':
                    layout.Resize_RB(-1, 0);
                    break;
                case 'd':
                    layout.Resize_RB(1, 0);
                    break;
                case 'S':
                    layout.Resize_LT(0, 1);
                    break;
                case 'W':
                    layout.Resize_LT(0, -1);
                    break;
                case 'A':
                    layout.Resize_LT(-1, 0);
                    break;
                case 'D':
                    layout.Resize_LT(1, 0);
                    break;
                case '9':
                    if(curr_win == _FILES)
                        layout.Shift(-1);
                    if(curr_win == _SRC || curr_win == _DBG )
                        h_code_layout.Shift(-1);
                    if(curr_win == _THREADS || curr_win == _CALL_STACK )
                        h_thr_call_layout.Shift(-1);
                    if(curr_win == _MEM || curr_win == _STACK)
                        h_mem_layout.Shift(-1);
                    break;
                case '0':
                    if(curr_win == _FILES)
                        layout.Shift(1);
                    if(curr_win == _SRC || curr_win == _DBG )
                        h_code_layout.Shift(1);
                    if(curr_win == _THREADS || curr_win == _CALL_STACK )
                        h_thr_call_layout.Shift(1);
                    if(curr_win == _MEM || curr_win == _STACK)
                        h_mem_layout.Shift(1);
                    break;
                case '-':
                    if(curr_win == _SRC || curr_win == _DBG )
                        v_code_layout.Shift(-1);
                    if(curr_win == _THREADS || curr_win == _CALL_STACK )
                        v_thr_call_layout.Shift(-1);
                    if(curr_win == _MEM || curr_win == _STACK)
                        v_mem_layout.Shift(-1);
                    break;
                case '=':
                    if(curr_win == _SRC || curr_win == _DBG )
                        v_code_layout.Shift(1);
                    if(curr_win == _THREADS || curr_win == _CALL_STACK )
                        v_thr_call_layout.Shift(1);
                    if(curr_win == _MEM || curr_win == _STACK)
                        v_mem_layout.Shift(1);
                    break;
                case 't':
                    if(win[curr_win].IsEnabled())
                        win[curr_win].Disable();
                    else
                        win[curr_win].Enable();
                    break;
                case '\t':
                    curr_win++;
                    if(curr_win >= _ALL_TYPE){
                        curr_win = 0;
                    }
                    win[curr_win].SetCurrent();
                    break;
            }
            win[curr_win].Paint();
        }
    }
    endwin();
    return 0;    
}

